﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wq.Core.Common.Helper
{
    public static class EnumHelper
    {
        public static T Parse<T>(string value)
        {
            return (T)Enum.Parse(typeof(T), value);
        }

        public static T Parse<T>(int value)
        {
            return Parse<T>(value.ToString());
        }

        public static int RemoveFlags(this int value, int flags)
        {
            var val1 = Convert.ToInt32(value);
            return (val1 & ~flags);
        }

        public static string ToDescription(this Enum value)
        {
            if (value == null)
                return string.Empty;
            var type = value.GetType();
            var items = GetEnumItems(type);
            var name = Enum.GetName(type, value);
            return items.FirstOrDefault(p => p.Name == name)?.Description ?? string.Empty;
        }

        public static Dictionary<int, string> ToDescriptionDictionary<TEnum>()
        {
            var type = typeof(TEnum);
            var items = GetEnumItems(type);
            return items.ToDictionary(k => k.Value, v => v.Description);

        }

        public static List<EnumItem> ToEnumItem<TEnum>()
        {
            var type = typeof(TEnum);
            var items = GetEnumItems(type);
            return items;
        }

        public class EnumItem
        {
            public string Name
            {
                get; set;
            }
            public int Value
            {
                get; set;
            }
            public string Description
            {
                get; set;
            }
        }
        static object initLock = new object();
        static ConcurrentDictionary<string, List<EnumItem>> enumDictionary = new ConcurrentDictionary<string, List<EnumItem>>();
        static List<EnumItem> GetEnumItems(Type type)
        {
            if (!enumDictionary.ContainsKey(type.FullName))
                InitEnum(type);
            return enumDictionary[type.FullName];
        }

        static void InitEnum(Type type)
        {
            lock (initLock)
            {
                if (!enumDictionary.ContainsKey(type.FullName))
                {
                    var data = type.GetFields()
                        .Where(p => p.FieldType.IsEnum).Select(item =>
                        {
                            var desc = (DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault();
                            return new EnumItem
                            {
                                Name = item.Name,
                                Value = Convert.ToInt32(item.GetValue(null)),
                                Description = desc?.Description ?? string.Empty
                            };
                        }).ToList();
                    enumDictionary.TryAdd(type.FullName, data);
                }
            }
        }
    }
}
